package com.ruoyi.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.business.SourceTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.HttpClientUtil;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.domain.UserThirdIdentity;
import com.ruoyi.user.domain.vo.AuthorizationVO;
import com.ruoyi.user.domain.vo.UserVo;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.user.service.IUserService;
import com.ruoyi.user.service.IUserThirdIdentityService;
import com.ruoyi.weixin.config.WxMaConfiguration;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 小程序用户管理Service业务层处理
 *
 * @author wuchao
 * @date 2022-03-03
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserServiceImpl implements IUserService {

    @Value("${wechat.miniapp.configs[0].appid}")
    private String appid;

    @Resource
    private final UserMapper baseMapper;

    @Resource
    private IUserThirdIdentityService userThirdIdentityService;


    /**
     * 查询小程序用户管理
     *
     * @param id 小程序用户管理主键
     * @return 小程序用户管理
     */
    @Override
    public UserVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AuthorizationVO authorization(String code) {
        WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            // session info
            UserThirdIdentity userThirdIdentity = userThirdIdentityService.getOne(
                Wrappers.lambdaQuery(UserThirdIdentity.class)
                    .eq(UserThirdIdentity::getIdentityUnionId, sessionInfo.getUnionid())
                    .eq(UserThirdIdentity::getIdentityOpenId, sessionInfo.getOpenid()));
            AuthorizationVO authorizationVO = AuthorizationVO.builder().wxMaJscode2SessionResult(sessionInfo).build();

            if (ObjectUtil.isEmpty(userThirdIdentity)) {
                // 存储 user 与 session info 信息
                User user = new User();
                long userId = IdWorker.getId();
                user.setId(userId);
                user.setNickname(Constants.USER_DEFAULT_NICKNAME);
                user.setTotalPoints(0);
                user.setFrozenPoints(0);
                user.setFreePoints(0);
                user.setStatus(0);
                user.setSourceType(SourceTypeEnum.NORMAL_REG.getCode());
                user.setCreateTime(new Date());
                user.setIsKoc(Constants.FALSE_0);
                user.setSourceType(SourceTypeEnum.NORMAL_REG.getCode());
                baseMapper.insert(user);
                // 插入用户 appId unionId
                UserThirdIdentity userThirdIdentityInsert = new UserThirdIdentity();
                userThirdIdentityInsert.setUserId(userId);
                userThirdIdentityInsert.setThirdType(1);
                userThirdIdentityInsert.setIdentityOpenId(sessionInfo.getOpenid());
                userThirdIdentityInsert.setIdentityUnionId(sessionInfo.getUnionid());
                userThirdIdentityService.getBaseMapper().insert(userThirdIdentityInsert);
                authorizationVO.setUserId(userId);
            } else {
                authorizationVO.setUserId(userThirdIdentity.getUserId());
            }
            return authorizationVO;
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public User check(String openId) {
        LambdaQueryWrapper<UserThirdIdentity> queryWrapper = Wrappers.lambdaQuery(UserThirdIdentity.class).eq(UserThirdIdentity::getIdentityOpenId, openId)
            .last(Constants.MYBATIS_PLUSH_LIMIT_ONE);
        UserThirdIdentity userThirdIdentity = userThirdIdentityService.getOne(queryWrapper);
        if (ObjectUtil.isEmpty(userThirdIdentity)) {
            return null;
        }
        return baseMapper.selectById(userThirdIdentity.getUserId());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public User registerOrLogin(String code, String openId, String unionId) {
        // 根据 openId 与 unionId 查询数据库中
        WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
        String accessToken;
        try {
            accessToken = wxMaService.getAccessToken();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        Map<String, String> postParam = new HashMap<>();
        postParam.put(Constants.WX_XCY_ACCESS_TOKEN, accessToken);
        Map<String, Object> jsonParamMap = new HashMap<>();
        jsonParamMap.put(Constants.WX_XCY_CODE, code);
        String res;
        try {
            res = HttpClientUtil.doPostJson(Constants.WX_XCY_CODE_PHONE_URL, postParam, jsonParamMap);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 根据手机号查询 数据库中 用户手机号是否存在
        JSONObject jsonObject;
        String phoneNumber;
        try {
            jsonObject = new JSONObject(res);
            if (jsonObject.getInt(Constants.WX_XCY_ERROR_CODE) == 0) {
                JSONObject phoneInfo = jsonObject.getJSONObject(Constants.WX_XCY_PHONE_INFO);
                phoneNumber = phoneInfo.getStr(Constants.WX_XCY_PHONE_NUMBER);
            } else {
                throw new ServiceException("接口异常");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 根据手机号查询 用户信息
        User queryByPhoneNumber = baseMapper.selectOne(Wrappers.lambdaQuery(User.class)
            .eq(User::getMobile, phoneNumber));

        // 根据 unionId 与 openid 查询用户
        UserThirdIdentity queryThirdIdentityByOpenIdAndUnionId = userThirdIdentityService.getOne(Wrappers.lambdaQuery(UserThirdIdentity.class)
            .eq(UserThirdIdentity::getIdentityOpenId, openId)
            .eq(UserThirdIdentity::getIdentityUnionId, unionId));

        User findUserByOpenIdAndUnionId = null;
        if (ObjectUtil.isNotEmpty(queryThirdIdentityByOpenIdAndUnionId)) {
            findUserByOpenIdAndUnionId = baseMapper.selectById(queryThirdIdentityByOpenIdAndUnionId.getUserId());
        }
        UserThirdIdentity queryThirdIdentityByUserId = null;
        // 根据 userId 查询 openid 与 unionId 获取用户信息
        if (ObjectUtil.isNotEmpty(findUserByOpenIdAndUnionId)) {
            queryThirdIdentityByUserId = userThirdIdentityService.getOne(Wrappers.lambdaQuery(UserThirdIdentity.class)
                .eq(UserThirdIdentity::getUserId, findUserByOpenIdAndUnionId.getId()));
        }
        User findUserByUserId = null;
        if (ObjectUtil.isNotEmpty(queryThirdIdentityByUserId)) {
            findUserByUserId = baseMapper.selectById(queryThirdIdentityByUserId.getUserId());
        }


        // 非koc 用户更新手机号
        if (ObjectUtil.isEmpty(queryByPhoneNumber) && Objects.equals(findUserByOpenIdAndUnionId.getIsKoc(), Constants.FALSE_0)) {
            // 根据手机号未查询到用户数据 并且是非koc用户 更新用户手机号
            findUserByOpenIdAndUnionId.setMobile(phoneNumber);
            findUserByOpenIdAndUnionId.setUpdateTime(new Date());
            baseMapper.updateById(findUserByOpenIdAndUnionId);
        }

        if (ObjectUtil.isNotEmpty(queryByPhoneNumber) && Objects.equals(queryByPhoneNumber.getIsKoc(), Constants.TRUE_1) && ObjectUtil.isEmpty(findUserByOpenIdAndUnionId)) {
            // 根据手机号查询到用户数据 并且是koc 用户 并且没有openid 与 unionId 数据
            //删除 用户 并更新用户
            baseMapper.deleteById(queryByPhoneNumber.getId());
            findUserByUserId.setMobile(phoneNumber);
            findUserByUserId.setRealName(queryByPhoneNumber.getRealName());
            findUserByUserId.setNickname(queryByPhoneNumber.getNickname());
            findUserByUserId.setGender(queryByPhoneNumber.getGender());
            findUserByUserId.setHeadPhoto(queryByPhoneNumber.getHeadPhoto());
            findUserByUserId.setSourceType(SourceTypeEnum.KOC_EXCEL_IMPORT.getCode());
            findUserByUserId.setIsKoc(Constants.TRUE_1);
            findUserByUserId.setKocLevelId(queryByPhoneNumber.getKocLevelId());
            findUserByUserId.setKocLevelTime(queryByPhoneNumber.getKocLevelTime());
            findUserByUserId.setKocLevelName(queryByPhoneNumber.getKocLevelName());
            findUserByUserId.setUpdateTime(new Date());
            baseMapper.updateById(findUserByUserId);
        }
        UserThirdIdentity queryIdentity = userThirdIdentityService.getOne(Wrappers.lambdaQuery(UserThirdIdentity.class)
            .eq(UserThirdIdentity::getIdentityOpenId, openId)
            .eq(UserThirdIdentity::getIdentityUnionId, unionId));
        return baseMapper.selectById(queryIdentity.getUserId());
    }

    @Override
    public User getById(Long userId, boolean isThrow) {
        User obj = this.baseMapper.selectById(userId);
        if (ObjectUtil.isNull(obj)) {
            if (isThrow) {
                throw new ServiceException("用户不存在");
            }
        }
        return obj;
    }
}
